﻿using Abp.Application.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NetCore.Dtos;
using NetCore.Entities;
using NetCore.Extensions;
using NetCore.Interfaces;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace NetCore.Services
{
    /// <summary>
    /// 基类AppService
    /// </summary>
    /// <typeparam name="TEntity">实体类</typeparam>
    /// <typeparam name="TPrimaryKey">实体类主键类型</typeparam>
    public abstract class BaseNetCoreAppService<TEntity, TPrimaryKey> : NetCoreAppServiceBase
        , IBaseNetCoreAppService<TEntity, TPrimaryKey>
        where TEntity : BaseEntity<TPrimaryKey>
    {
        public INetCoreRepository<TEntity, TPrimaryKey> BaseRepository;

        protected BaseNetCoreAppService(INetCoreRepository<TEntity, TPrimaryKey> baseRepository)
        {
            BaseRepository = baseRepository;
        }

        #region 实体增删改查

        /// <summary>
        /// 获取实体BaseRepository
        /// </summary>
        /// <returns></returns>
        public INetCoreRepository<TEntity, TPrimaryKey> GetBaseRepository()
        {
            return BaseRepository;
        }

        /// <summary>
        /// 根据主键获取实体
        /// </summary>
        /// <param name="input">实体主键输入类</param>
        /// <returns></returns>
        [Description("根据主键获取实体")]
        public virtual TEntity Get(InputIdDto<TPrimaryKey> input)
        {
            return BaseRepository.Get(input.Id);
        }

        /// <summary>
        /// 表达式目录树filter参数过滤数据 提供给内部使用
        /// </summary>
        /// <param name="filter">表达式目录树</param>
        /// <returns></returns>
        protected IQueryable<TEntity> Get(Expression<Func<TEntity, bool>> filter)
        {
            return BaseRepository.GetAll().Where(filter);
        }

        /// <summary>
        /// 异步判断是否有数据
        /// </summary>
        /// <returns></returns>
        protected async Task<bool> AnyAsync()
        {
            return await BaseRepository.GetAll().AnyAsync();
        }

        /// <summary>
        /// 根据条件判断是否有数据
        /// </summary>
        /// <param name="filter">实体过滤器表达式目录树</param>
        /// <returns></returns>
        protected async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> filter)
        {
            return await BaseRepository.GetAll().AnyAsync(filter);
        }

        /// <summary>
        /// 异步判断是否存在
        /// </summary>
        /// <param name="filter">实体过滤器表达式目录树</param>
        /// <returns></returns>
        protected async Task<bool> IsExsitAsync(Expression<Func<TEntity, bool>> filter)
        {
            return await AnyAsync(filter);
        }

        ///// <summary>
        ///// 异步修改实体
        ///// </summary>
        ///// <param name="entity">实体</param>
        ///// <returns></returns>
        //[Description("异步修改实体")]
        //public virtual async Task<TEntity> UpdateAsync(TEntity entity)
        //{
        //    //JsonConvert.PopulateObject(entityJsonString, entity);
        //    return await BaseRepository.UpdateAsync(entity);
        //}


        /// <summary>
        /// 异步添加实体
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        [Description("异步添加实体")]
        public virtual async Task<TEntity> InsertAsync(TEntity entity)
        {
            return await BaseRepository.InsertAsync(entity);
        }

        /// <summary>
        /// 批量添加实体
        /// </summary>
        /// <param name="entities">实体集</param>
        /// <returns></returns>
        [Description("批量添加实体")]
        public virtual async Task<IActionResult> BulkInsertAsync(IList<TEntity> entities)
        {
            await BaseRepository.BulkInsertAsync(entities);
            return SJson();
        }

        /// <summary>
        /// 根据主键删除实体
        /// </summary>
        /// <param name="input">主键Id</param>
        /// <returns></returns>
        [Description("删除数据")]
        public virtual IActionResult Delete(InputIdDto<TPrimaryKey> input)
        {
            BaseRepository.Delete(input.Id);
            return SJson();
        }

        /// <summary>
        /// 根据主键异步删除实体
        /// </summary>
        /// <param name="input">实体主键</param>
        /// <returns></returns>
        [Description("根据主键异步删除实体")]
        public virtual async Task<IActionResult> DeleteAsync(InputIdDto<TPrimaryKey> input)
        {
            await BaseRepository.DeleteAsync(input.Id);
            return SJson();
        }

        /// <summary>
        /// 批量删除实体 RemoteService(false)不被自动编译成 WebApi 但仍然为public提供给controller层手动调用
        /// </summary>
        /// <param name="entities">实体集</param>
        /// <returns></returns>
        [RemoteService(false), Description("批量删除实体")]
        public virtual async Task<IActionResult> BulkDeleteEntityAsync(IList<TEntity> entities)
        {
            await BaseRepository.BulkDeleteAsync(entities);
            return SJson();
        }

        /// <summary>
        /// 批量删除实体
        /// </summary>
        /// <param name="ids">实体主键集合</param>
        /// <returns></returns>
        [Description("批量删除实体")]
        public virtual async Task<IActionResult> BulkDeleteAsync(IList<TPrimaryKey> ids)
        {
            var entities = await BaseRepository.GetAll().Where(m => ids.Contains(m.Id)).ToListAsync();
            return await BulkDeleteEntityAsync(entities);
        }
        #endregion

        #region 重复性验证 重新设计
        /// <summary>
        /// 单字段重复性验证
        /// </summary>
        /// <param name="field">单个字段选项</param>
        /// <returns></returns>
        [HttpPost]
        public virtual IActionResult CheckFieldUnique(FieldCheckOptionDto<TPrimaryKey> field)
        {
            var query = BaseRepository.GetAll();
            var isRepeat = query.Any();//如果没有数据，默认为false 表示没有重复
            if (isRepeat)
            {
                if (!field.Equal) field.Equal = true;
                var dynamicFieldExpression = ExpressionExtension.DynamicField<TEntity, TPrimaryKey>(field);
                query = query.Where(dynamicFieldExpression);
                isRepeat = query.Any();//是否重复
            }
            return DJson(isRepeat);
        }
        /// <summary>
        /// 多字段重复性验证，dxGrid在新建/编辑数据时 时时验证
        /// </summary>
        /// <param name="fields">多字段dto选项</param>
        /// <returns></returns>
        [HttpPost]
        public virtual IActionResult CheckFieldsUnique(List<FieldCheckOptionDto<TPrimaryKey>> fields)
        {
            var query = BaseRepository.GetAll();
            var isRepeat = query.Any();//如果没有数据，默认为false 前端返回true表示通过
            if (isRepeat)
            {
                foreach (var field in fields)
                {
                    query = query.Where(field.CheckLambda<TEntity, TPrimaryKey>());//构造表达式目录树
                }
                isRepeat = query.Any();//根据条件验证是否重复
            }

            return DJson(isRepeat);
        }

        #endregion

    }

    /// <summary>
    /// 基类Appservices 
    /// </summary>
    /// <typeparam name="TEntity">实体类</typeparam>
    public class BaseNetCoreAppService<TEntity> : BaseNetCoreAppService<TEntity, int>
        , IBaseNetCoreAppService<TEntity>
        where TEntity : BaseEntity
    {
        public BaseNetCoreAppService(INetCoreRepository<TEntity> baseRepository) : base(baseRepository)
        {
        }
    }

}
